package com.code.filter;

import com.alibaba.fastjson.JSON;
import com.code.constant.LoginConstant;
import com.code.model.Result;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * token校验的过滤器
 */
@Component
public class TokenCheckFilter extends OncePerRequestFilter {

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 1.拿到请求路径
     * 2.判断是否需要放行
     * 3.拿到请求头
     * 4.拿到token
     * 5.查询redis 换用户对象
     * 6.放在securityContext中
     *
     * @param request
     * @param response
     * @param filterChain
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        response.setContentType("application/json;charset=utf-8");
        String path = request.getRequestURI();
        for (String allowPath : LoginConstant.ALLOW_URL) {
            if (allowPath.equals(path)) {
                filterChain.doFilter(request, response);
                return;
            }
        }
        if (path.contains("swagger") || path.contains("api-docs")) {
            filterChain.doFilter(request, response);
            return;
        }
        // 校验token
        String authorization = request.getHeader(LoginConstant.AUTHORIZATION);
        if (StringUtils.hasText(authorization)) {
            String token = authorization.replaceAll(LoginConstant.TOKEN_PREFIX, "");
            if (StringUtils.hasText(token)) {
                // 从redis里取
                String userStr = redisTemplate.opsForValue().get(LoginConstant.LOGIN_PREFIX + token);
                if (StringUtils.hasText(userStr)) {
                    // 将用户反转出来
                    UsernamePasswordAuthenticationToken authenticationToken = JSON.parseObject(userStr, UsernamePasswordAuthenticationToken.class);
                    // 放到上下文中 就是为了让security知道用户登录了
                    SecurityContextHolder.getContext().setAuthentication(authenticationToken);
                    // 放行
                    filterChain.doFilter(request, response);
                    return;
                }
            }
        }
        // 拦截
        Result<Object> result = new Result<>();
        result.setCode(401);
        result.setMsg("请重新登录");
        ObjectMapper objectMapper = new ObjectMapper();
        String s = objectMapper.writeValueAsString(result);
        PrintWriter writer = response.getWriter();
        writer.write(s);
        writer.flush();
        writer.close();
    }
}
